﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.UnityExtensions;
using System.Windows;
using ALPShell.ViewModel;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.Events;
using Infrastructure.Events;
using System.Threading;
using Microsoft.Practices.Prism.Regions;

namespace ALPShell
{
    public class ALPBootstrapper : UnityBootstrapper
    {
        private LogonWindow logonWindow;
        private IModuleManager moduleManager;
        private IEventAggregator eventAggregator;

        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog catalog = new ConfigurationModuleCatalog();
            return catalog;
        }

        protected override DependencyObject CreateShell()
        {
            moduleManager = Container.Resolve<IModuleManager>();
            moduleManager.LoadModuleCompleted += new EventHandler<LoadModuleCompletedEventArgs>(moduleManager_LoadModuleCompleted);
            eventAggregator = Container.Resolve<IEventAggregator>();
            eventAggregator.GetEvent<BeginInitializeModulesEvent>().Subscribe(OnBeginInitializeModules);
            eventAggregator.GetEvent<CompleteInitializeModulesEvent>().Subscribe(OnCompleteInitializeModules);

            logonWindow = Container.Resolve<LogonWindow>();
            logonWindow.DataContext = Container.Resolve<LogonWindowViewModel>();


            return logonWindow;
        }

        protected void OnBeginInitializeModules(object o)
        {
            eventAggregator.GetEvent<CompleteInitializeModulesEvent>().Publish(null);
        }

        protected void OnCompleteInitializeModules(object o)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                var shell = Container.Resolve<ShellWindow>();
                var vm = Container.Resolve<ShellViewModel>();
                shell.DataContext = vm;
                RegionManager.SetRegionManager(shell, this.Container.Resolve<IRegionManager>());
                RegionManager.UpdateRegions();
                if (shell != null)
                {
                    shell.ShowInTaskbar = true;
                    shell.WindowState = WindowState.Maximized;
                    shell.Show();

                    LoadModulesOnDemand();

                    App.Current.MainWindow = shell;
                    App.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
                    eventAggregator.GetEvent<KillAppEvent>().Publish(new KillAppEventPayload { IsKeptAlive = true });
                }
            }));

            ThreadPool.QueueUserWorkItem((s) =>
            {
                GC.Collect();
                GC.WaitForFullGCComplete(Timeout.Infinite);
                GC.Collect();
            });
        }

        private void LoadModulesOnDemand()
        {
            foreach (var module in ModuleCatalog.Modules)
            {
                if (module.InitializationMode == InitializationMode.OnDemand)
                {
                    try
                    {
                        moduleManager.LoadModule(module.ModuleName);
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
        }

        void moduleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
        {
            App.SplashScreen.Close(System.TimeSpan.FromSeconds(.2));
            App.Current.Dispatcher.BeginInvoke(new System.Action(() => logonWindow.Show()));
            moduleManager.LoadModuleCompleted -= new EventHandler<LoadModuleCompletedEventArgs>(moduleManager_LoadModuleCompleted);
        }
    }
}
